package gogen

import (
	_ "embed"
	"fmt"
	"strings"

	"github.com/zeromicro/go-zero/tools/goctl/api/spec"
	"github.com/zeromicro/go-zero/tools/goctl/config"
	"github.com/zeromicro/go-zero/tools/goctl/util/format"
	"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)

//go:embed main.tpl
var mainTemplate string

//go:embed httpxresponse.tpl
var httpxResponseTemplate string

//go:embed httpxrequest.tpl
var httpxRequestTemplate string

//go:embed xerr.tpl
var xerrTemplate string

//go:embed Makefile.tpl
var makefileTemplate string

//go:embed dockerfile.tpl
var dockerfileTemplate string

func genMain(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error {
	name := strings.ToLower(api.Module)
	filename, err := format.FileNamingFormat(cfg.NamingFormat, name)
	if err != nil {
		return err
	}

	serverName := filename
	if strings.HasSuffix(filename, "-api") {
		filename = strings.ReplaceAll(filename, "-api", "")
	}

	if err = genHttpxResponse(dir); err != nil {
		return err
	}
	if err = genHttpxRequset(dir); err != nil {
		return err
	}
	if err = genXerrRequset(dir); err != nil {
		return err
	}
	if err = genMakefile(dir, serverName); err != nil {
		return err
	}
	if err = genDockerfile(dir, serverName); err != nil {
		return err
	}

	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "",
		filename:        "main.go",
		templateName:    "mainTemplate",
		category:        category,
		templateFile:    mainTemplateFile,
		builtinTemplate: mainTemplate,
		data: map[string]string{
			"defaultMod":     strings.Title(api.Module),
			"moduleCase":     genMainModuleCase(api.Module),
			"moduleConst":    genMainModuleConst(api.Module),
			"importPackages": genMainImports(rootPkg, api.Module),
			"serviceName":    serverName,
		},
	})
}

func genMainModuleCase(module string) string {
	return fmt.Sprintf("case %s:\n		srv = %s.NewHandle(svc)", strings.Title(module), module)
}

func genMainModuleConst(module string) string {
	return fmt.Sprintf("%s = \"%s\"", strings.Title(module), module)
}

func genMainImports(parentPkg, module string) string {
	var imports []string
	module = handlerDir + "/" + module
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, configDir)))
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, module)))
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, contextDir)))
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, "pkg/conf")))
	return strings.Join(imports, "\n\t")
}

func genHttpxResponse(dir string) error {
	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "pkg/httpx",
		filename:        "response.go",
		templateName:    "httpxresponseTemplate",
		category:        "",
		templateFile:    "httpxresponse.tpl",
		builtinTemplate: httpxResponseTemplate,
		data:            map[string]string{},
	})
}
func genHttpxRequset(dir string) error {
	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "pkg/httpx",
		filename:        "request.go",
		templateName:    "httpxrequestTemplate",
		category:        "",
		templateFile:    "httpxrequset.tpl",
		builtinTemplate: httpxRequestTemplate,
		data:            map[string]string{},
	})
}
func genXerrRequset(dir string) error {
	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "pkg/xerr",
		filename:        "xerr.go",
		templateName:    "xerrTemplate",
		category:        "",
		templateFile:    "xerr.tpl",
		builtinTemplate: xerrTemplate,
		data:            map[string]string{},
	})
}

func genMakefile(dir, serverName string) error {
	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "",
		filename:        "Makefile",
		templateName:    "makefileTemplate",
		category:        "",
		templateFile:    "Makefile.tpl",
		builtinTemplate: makefileTemplate,
		data: map[string]string{
			"server": serverName,
		},
	})
}

func genDockerfile(dir, serverName string) error {
	err := genFile(fileGenConfig{
		dir:             dir,
		subdir:          "deploy",
		filename:        "dockerfile_dev",
		templateName:    "dockerfileTemplate",
		category:        "",
		templateFile:    "dockerfile.tpl",
		builtinTemplate: dockerfileTemplate,
		data: map[string]string{
			"server": serverName,
			"mod":    "dev",
		},
	})
	if err != nil {
		return err
	}

	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          "deploy",
		filename:        "dockerfile_prod",
		templateName:    "dockerfileTemplate",
		category:        "",
		templateFile:    "dockerfile.tpl",
		builtinTemplate: dockerfileTemplate,
		data: map[string]string{
			"server": serverName,
			"mod":    "prod",
		},
	})
}
